home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / magazyn_amiga / 2 / ami044_kurs_c.txt < prev    next >
Text File  |  1997-09-14  |  10KB  |  236 lines

  1. C dla kaûdego (cz. 9.)
  2. ----------------------
  3.  
  4. PISANIA CIÂG DALSZY
  5.  
  6. <lead>Zakoïczymy dziô rozpoczëte przed miesiâcem rozwaûania na
  7. temat czcionek. Listing, który dziô zaprezentujemy, nie powinien
  8. byê nowoôciâ. Myôlë, ûe pracowity Czytelnik po lekturze
  9. poprzedniego odcinka ma juû jakieô pojëcie o otwieraniu czcionek.
  10.  
  11. <a>Kamil Iskra, Dariusz Ûbik
  12.  
  13. <txt>Funkcja OpenDiskFont() otwiera czcionkë najbardziej zbliûonâ
  14. do opisu, jednak nie zawsze dostëpna na dysku czcionka odpowiada
  15. naszym wymaganiom. W takim wypadku moûliwe jest wygenerowanie
  16. ûâdanych atrybutów. Sîuûy do tego funkcja:
  17.  
  18. <l>ULONG SetSoftStyle( struct RastPort *rp, ULONG style, ULONG enable );
  19.  
  20. <txt>Funkcja zmienia styl czcionki uûywanej przez RastPort "rp"
  21. na styl opisany za pomocâ parametru "style" (moûliwe pochylenie,
  22. pogrubienie i podkreôlenie -- patrz poprzednia czëôê). Funkcja
  23. zwraca flagi stylu, który udaîo sië uzyskaê. Argument "enable"
  24. jest maskâ bitowâ, zezwalajâcâ na zastosowanie poszczególnych
  25. atrybutów. W zaleûnoôci od upodobaï twórcy czcionki nie wszystkie
  26. atrybuty mogâ byê programowo generowane (bo na przykîad czcionka
  27. zostaîa od razu zaprojektowana jako pochylona), argument "enable"
  28. powinien mieê ustawione te bity, które odpowiadajâ moûliwym do
  29. generowania trybom. Aby uzyskaê informacje, które atrybuty sâ
  30. dozwolone, naleûy skorzystaê z funkcji:
  31.  
  32. <l>ULONG AskSoftStyle( struct RastPort *rp );
  33.  
  34. <txt>Funkcja ta zwraca wartoôê, która jest maskâ bitowâ
  35. wszystkich moûliwych atrybutów czcionki, uûywanej aktualnie w
  36. podanym jako argument RastPorcie.
  37.  
  38. Informacje o stylach, które zostaîy wygenerowane, moûna znaleúê w
  39. polu "AlgoStyle" struktury "RastPort".
  40.  
  41. Kwestië otwarcia czcionki i ustalenia jej stylu mamy juû za sobâ.
  42. Najwyûszy czas wziâê sië do pisania.
  43.  
  44. Najprostszâ funkcjâ, piszâcâ po RastPorcie, jest zaprezentowana
  45. juû w czëôci szóstej funkcja z "graphics.library":
  46.  
  47. <l>LONG Text( struct RastPort *rp, STRPTR string, ULONG count );
  48.  
  49. <txt>Funkcja ta uznaje ustawienia RastPortu, takie jak kolory,
  50. tryb rysowania i, rzecz jasna, czcionkë. Poniewaû istniejâ
  51. czcionki proporcjonalne, okreôlenie dîugoôci napisu wykonanego
  52. takâ czcionkâ moûe byê kîopotliwe. W tym celu biblioteka
  53. graficzna zostaîa wyposaûona w funkcje, pozwalajâce wyliczyê
  54. rozmiary napisu. Pierwszâ i jednoczeônie najstarszâ jest:
  55.  
  56. <l>WORD TextLength( struct RastPort *rp, STRPTR string, ULONG count );
  57.  
  58. <txt>Funkcja ta okreôla, o ile punktów w poziomie przesunie sië
  59. kursor graficzny po wypisaniu w RastPorcie napisu, wskazywanego
  60. przez "string", o dîugoôci odnotowanej w argumencie "count".
  61. Informacja ta nie zawsze jest w peîni wystarczajâca, poniewaû w
  62. wypadku czcionek pochylonych wystëpujâ rozbieûnoôci pomiëdzy
  63. ostatnim zajëtym przez napis punktem a poîoûeniem kursora po
  64. umieszczeniu napisu (patrz rysunek -- czerwonymi krzyûykami
  65. oznaczono kursor graficzny przed i po umieszczeniu tekstu w
  66. RastPorcie).
  67.  
  68. Kolejnâ funkcjâ, pomocnâ w okreôleniu rozmiarów napisu, jest
  69. TextExtent(). Pojawiîa sië ona w systemie operacyjnym 2.0:
  70.  
  71. <l>void TextExtent( struct RastPort *rp, STRPTR string, long count, struct 
  72. TextExtent *textExtent );
  73.  
  74. <txt>Trzy pierwsze argumenty sâ analogiczne do argumentów funkcji
  75. TextLength(). Czwarty argument jest wskaúnikiem na strukturë
  76. "TextExtent", zdefiniowanâ w "graphics/text.h", w której zostanâ
  77. umieszczone rezultaty.
  78.  
  79. <l>struct TextExtent
  80.  
  81. {
  82.  
  83.    UWORD te_Width;
  84.  
  85.    UWORD te_Height;
  86.  
  87.    struct Rectangle te_Extent;
  88.  
  89. };
  90.  
  91. <txt>Po wywoîaniu funkcji struktura ta zostanie wypeîniona w
  92. sposób nastëpujâcy:
  93.  
  94. "te_Width" -- zawiera të samâ wartoôê, którâ zwraca funkcja
  95. TextLength(), czyli przesuniëcie kursora graficznego, jakie
  96. spowoduje wypisanie napisu.
  97.  
  98. "te_Height" -- zawiera wysokoôê napisu, czyli "tf_YSize" czcionki.
  99.  
  100. Kolejne pole jest strukturâ "Rectangle", przeznaczonâ do opisu
  101. prostokâta:
  102.  
  103. <l>struct Rectangle
  104.  
  105. {
  106.  
  107.    WORD MinX, MinY;
  108.  
  109.    WORD MaxX, MaxY;
  110.  
  111. };
  112.  
  113. <txt>W naszym wypadku struktura ta opisuje obszar, który ulegnie
  114. zmianie po wypisaniu napisu. Wszystkie wspóîrzëdne sâ liczone
  115. wzglëdem obecnego poîoûenia kursora graficznego w RastPorcie,
  116. oznaczajâ wiëc:
  117.  
  118. "te_Extent.MinX" -- odlegîoôê pomiëdzy pozycjâ "cp_x" kursora w
  119. RastPorcie a lewâ krawëdziâ prostokâta, zawierajâcego napis --
  120. wartoôê ta bywa ujemna;
  121.  
  122. "te_Extent.MinY" -- odlegîoôê pomiëdzy pozycjâ "cp_y" kursora (a
  123. wiëc liniâ bazowâ) a górnâ krawëdziâ prostokâta -- równieû bywa
  124. ujemna;
  125.  
  126. "te_Extent.MaxX" -- odlegîoôê pomiëdzy pozycjâ "cp_x" kursora a
  127. prawâ krawëdziâ prostokâta;
  128.  
  129. "te_Extent.MaxY" -- odlegîoôê pomiëdzy pozycjâ "cp_y" kursora (a
  130. wiëc liniâ bazowâ) a dolnâ krawëdziâ prostokâta.
  131.  
  132. W szczególnym wypadku stosowania czcionek "normalnych" pole
  133. "te_Extent.MinX" wynosi 0.
  134.  
  135. Wiem, ûe nie jest to oczywiste, wiëc proponujë przeanalizowaê
  136. rysunek. Kolorem zielonym zaznaczone sâ wspóîrzëdne, otrzymane
  137. po przesuniëciu kursora graficznego o wartoôci zapisane w
  138. strukturze "Rectangle". Linia górna jest wynikiem przesuniëcia
  139. kursora w pionie o wartoôê "MinY", linia dolna -- "MaxY", lewa --
  140. "MinX", prawa -- "MaxX". Linia koloru niebieskiego jest wynikiem
  141. przesuniëcia kursora o wartoôê "te_Width".
  142.  
  143. Caîkowita dîugoôê prostokâta, zawierajâcego napis, wynosi wiëc
  144. te_Extent.MaxX-te_Extent.MinX+1. Z wysokoôciâ jest analogicznie,
  145. moûna równieû skorzystaê z pola "tf_YSize" czcionki.
  146.  
  147. Jeôli ktoô chciaîby narysowaê ramkë na zewnâtrz napisu, to
  148. wystarczy zmniejszyê o 1 pola "MinX" i "MinY" oraz zwiëkszyê o 1
  149. "MaxX" i "MaxY". Dziëki zmianie wartoôci tych pól ramka bëdzie
  150. narysowana na zewnâtrz prostokâta zawierajâcego napis.  Wykonanie
  151. ramki jest przedstawione w przykîadzie (funkcja border()).
  152.  
  153. Za pomocâ funkcji TextExtent() moûna sprawdziê, ile liter danego
  154. napisu zmieôci sië w RastPorcie. Wystarczy umieôciê të funkcjë w
  155. pëtli zmniejszajâcej przy kaûdym obrocie wartoôê "count" i
  156. wykonujâcej sië aû do chwili, gdy napis zmieôci sië w ûâdanym
  157. obszarze. Poniewaû potrzeba taka zachodzi doôê czësto, powstaîo
  158. do tego celu narzëdzie systemowe. Funkcja TextFit(), bo o niej
  159. mowa, jako wynik dziaîania zwraca liczbë znaków, którâ moûna
  160. wpisaê do podanego obszaru. Wypeînia ona równieû podanâ strukturë
  161. "TextExtent", która zawiera dokîadnie te same informacje, co w
  162. wypadku poprzedniej funkcji. Jedyna róûnica polega na tym, ûe
  163. informacje te dotyczâ napisu o dîugoôci równej wartoôci zwróconej
  164. przez funkcjë.
  165.  
  166. <l>ULONG TextFit( struct RastPort *rp, STRPTR string, ULONG strLen, struct 
  167. TextExtent *textExtent, struct TextExtent *constrainingExtent, long 
  168. strDirection, ULONG constrainingBitWidth, ULONG constrainingBitHeight );
  169.  
  170. <txt>Argumenty "rp", "string", "strLen" oraz "textExtent" sâ
  171. analogiczne do argumentów poprzedniej funkcji. Argument
  172. "strDirection" ustala, w którâ stronë majâ byê naliczane znaki --
  173. zwykle podaje sië 1, wtedy funkcja informuje, ile pierwszych
  174. liter napisu "string" sië zmieôci. Gdy poda sië -1, a jako
  175. "string" koniec napisu, wtedy funkcja wyliczy, ile ostatnich
  176. liter napisu sië zmieôci.
  177.  
  178. Do funkcji naleûy przekazaê wymiary obszaru, na którym ma byê
  179. umieszczony napis. Wedle posiadanej przez nas dokumentacji
  180. wymiary te moûna przekazaê na dwa sposoby: albo podajâc
  181. wypeînionâ strukturë "TextExtend" jako parametr
  182. "constrainingExtent", albo podajâc tam NULL, a szerokoôê i
  183. wysokoôê w polach "constrainingBitWidth" i
  184. "constrainingBitHeight". Drugi sposób dziaîa bez zarzutu, jednak
  185. pierwszy jest zupeînie nie udokumentowany. Darek usiîowaî
  186. rozszyfrowaê, "co jest grane", eksperymentujâc, ale doszedî do
  187. dziwacznych wniosków, których nie zamierzamy tu prezentowaê.
  188. Polecamy wiëc uûywaê tylko drugiego sposobu, który zresztâ w
  189. praktyce w peîni wystarcza.
  190.  
  191. Najwyûsza pora zaprezentowaê przykîad. W dzisiejszym listingu po
  192. raz pierwszy skorzystamy z biblioteki pochodzâcej z dysku. W
  193. takim wypadku koniecznie trzeba wziâê pod uwagë moûliwoôê
  194. zwrócenia NULL przez OpenLibrary() (bo np. uûytkownik mógî
  195. bibliotekë skasowaê z dysku). Prawdziwy program uûytkowy powinien
  196. poinformowaê o jej braku, nam w przykîadzie szkoda na to miejsca.
  197.  
  198. W wypadku bibliotek, znajdujâcych sië w ROM-ie, takich jak
  199. "intuition" czy "graphics", moûna z czystym sumieniem zrezygnowaê
  200. ze sprawdzania, czy próba ich otwarcia zostaîa uwieïczona
  201. sukcesem, co teû czynië w przykîadzie.
  202.  
  203. Przykîad oczekuje jednego parametru w linii argumentowej -- nazwy
  204. czcionki, którâ bëdzie "maltretowaî".
  205.  
  206. W jednym z poprzednich odcinków obiecaîem, ûe pokaûë, jak obejôê
  207. sië bez "WFLG_GIMMEZEROZERO", wîaônie to robië:
  208.  
  209. Struktura "Window" zawiera pola, w których zapisana jest
  210. szerokoôê poszczególnych ramek okna. Pola "BorderLeft",
  211. "BorderTop", "BorderRight", "BorderBottom" zawierajâ szerokoôci
  212. odpowiednio lewej, górnej, prawej i dolnej ramki. Aby nie
  213. "papraê" po ramkach, wystarczy pamiëtaê, ûe "dozwolony" obszar
  214. zaczyna sië poniûej górnej i na prawo od lewej ramki, oraz
  215. powyûej dolnej i na lewo od prawej. W przykîadzie korzystam ze
  216. struktury "Rectangle", w której na poczâtku odnotowujë wolny
  217. obszar okna, a nastëpnie sukcesywnie zmniejszam go, umieszczajâc
  218. w RastPorcie napisy.
  219.  
  220. Moûe Was zastanawiaê, dlaczego sprawdzajâc, czy jest cokolwiek do
  221. napisania, sprawdzamy zarówno, czy TextFit() zwróciîa wartoôê
  222. niezerowâ, jak i to, czy za napisem bëdzie jeszcze przewidziane
  223. przez nas wolne miejsce. Powinien wîaôciwie wystarczyê ten
  224. pierwszy test. Wyglâda jednak na to, ûe funkcja TextFit() ma
  225. bîâd -- gdy "da" sië jej zbyt maîo miejsca, to czasami "wydaje"
  226. jej sië, ûe ma go w bród i "udziela nieprawdziwych informacji",
  227. naleûy wiëc zweryfikowaê otrzymane wyniki.
  228.  
  229. W pëtli do-while zastosowaîem skrót, pozwalajâcy cyklicznie
  230. zmieniaê atrybuty czcionki. Skrót ten jest dokîadnie taki sam,
  231. jak w poprzednim listingu. Tamten dotyczyî trybu rysowania w
  232. RastPorcie.
  233.  
  234. Na koniec przypominam, ûe polecenie preprocesora "#undef"
  235. powoduje "zapomnienie" o poprzedniej definicji makra.
  236.